<?php
class AppController extends Controller {
    var $components = array('Acl','RequestHandler');
    var $helpers = array('Javascript','Html','Ajax','PhpSpeedy');
    var $uses = array('Cierre','Usuario','Ejercicio','Grupo','CentroDist','Aro','ArosCentroDist');
    var $grupos_despacho = array(1,3,6,9,16,22,26);
    var $logistica = array(3,11);
    var $gerencia  = array(16);
    var $_usuario;
    var $_ejercicio;
    public static $text_buscar;
    public static $limit_index;
    var $appModule = 'General';
    var $appName = 'ERP ADCsoft';
    var $limite = 20;
    var $externalAccess = false;
    var $path_webroot = WWW_ROOT; //C:\\...\webroot\
    var $homeUrl = array('controller'=>'Home','action'=>'index');
    var $indexUrl = array('action'=>'index');
    var $loginExceptions = array(
        'Pages'=>'display',
        'Usuarios'=>array('login', 'logout'),
        'TipoCambios'=>array('proxyUpdateChange'),
        'Kardex'=>array('proxyRecalcularSaldos'),
        'NextelWebservice'=>array('proxyCargarCobranzas')
    );
    var $accessActions = array(
        'create'=>array(
            '/^[[:alnum:]]*.add[[:alnum:]]*/',
            '/^Cierres.apertura[[:alnum:]]*/'
        ),
        'update'=>array(
            '/^[[:alnum:]]*.reasignar$/',
            '/^[[:alnum:]]*.modelos_marca$/',
            '/^[[:alnum:]]*.execute$/',
            '/^OrdenSalidas.manager$/',
            '/^OrdenSalidas.register$/',
            '/^OrdenSalidas.liquidar$/',
            '/^[[:alnum:]]*.addedit$/',
            '/^[[:alnum:]]*.edit[[:alnum:]]*$/',
            '/^[[:alnum:]]*.printdocument$/',
            '/^[[:alnum:]]*.calificaciones$/',
            '/^[[:alnum:]]*.certicom$/',
            '/^[[:alnum:]]*.documentos$/'
        ),
        'delete'=>array(
            '/^[[:alnum:]]*.anular$/',
            '/^[[:alnum:]]*.borrar$/',
            '/^[[:alnum:]]*.delete[[:alnum:]]*$/',
            '/^[[:alnum:]]*.*delete$/',
            '/^[[:alnum:]]*.cancel$/',
            '/^[[:alnum:]]*.process$/'
        ),
        'read'=>array(
            '/^[[:alnum:]]*.[[:alnum:]]*$/'
        )
    );

    var $months = array('ENERO','FEBRERO','MARZO','ABRIL','MAYO','JUNIO','JULIO','AGOSTO','SETIEMBRE','OCTUBRE','NOVIEMBRE','DICIEMBRE');
    var $periodos = array('-----','ENERO','FEBRERO','MARZO','ABRIL','MAYO','JUNIO','JULIO','AGOSTO','SETIEMBRE','OCTUBRE','NOVIEMBRE','DICIEMBRE');
	public $mensaje = array(
		'Error_add'=>'Error:El resgistro no pudo ser guardado.',
		'Error_edit'=>'Error:El resgistro no pudo ser modificado.',
		'Error_delete'=>'Error:El resgistro no pudo ser borrado.',
		'Error_anular'=>'Error:El resgistro no pudo ser anulado.',
		'Information'=>'La operación se realizo satisfactoriamente',
	);	
	var $tipoProducto = array(
		0=>array(1,2), // PRODUCTO TERMINADO
		1=>array(3,4), // MATERIA PRIMA
	);


    var $UPLOAD_PERMITTED_FILES = array(
        0 => array('image/gif','image/jpeg','image/pjpeg','image/png'),
        1 => array('application/vnd.ms-excel')
    );	
    
    public static $_mpdf;

    function __construct() {
        parent::__construct();        
        $this->pageTitle = $this->appName." [".$this->name."]";        
		/*define('_HEADER_DEFAULT_',false);
		define('_FOOTER_DEFAULT_',false);*/
    }

    // ****** Layout
    function reporte_html(){
            Configure::write('debug', 0);
            set_time_limit(0);
            $this->layout ='reporte_html';
    }
	
    function reporte_doc(){
        Configure::write('debug', 0);
        set_time_limit(0);
        $this->layout ='reporte_doc';
    }

    function ajax_html(){
            Configure::write('debug', 0);            
            $this->layout ='ajax';
    }
    
    /**
     * permite subir imágenes al servidor
     * @param string $folder la carpeta donde sera subido el archivo e.g. 'img/files'
     * @param array $formdata El array que contiene el archivo
     * @param int $itemId Id (optional) del elemento donde se creara la nueva subcarpeta
     * @param int $permitted Id (optional) de los tipos de archivo permitidos ver UPLOAD_PERMITTED_FILES
     * @return array
     *          will return an array with the success of each file upload
     *		img/$folder/$formdata['file']['name']	-->si es nombre unico
     *		img/$folder/{fecha 'dd-mm-yyyy'}-{random}$formdata['file']['name']	-->si es nombre duplicado
     */
    function uploadFiles($folder, $formdata, $itemId = null, $permitted = 0) {
        // setup dir names absolute and relative
        $folder_url = WWW_ROOT.$folder;
        $rel_url = $folder;

        // create the folder if it does not exist
        if(!is_dir($folder_url)) {
                mkdir($folder_url);
        }
        
        // if itemId is set create an item folder
        if($itemId) {
                // set new absolute folder
                $folder_url = WWW_ROOT.$folder.'/'.$itemId;
                // set new relative folder
                $rel_url = $folder.'/'.$itemId;
                // create directory
                if(!is_dir($folder_url)) {
                        mkdir($folder_url);
                }
        }

        // list of permitted file types, this is only images but documents can be added
			//print_r($formdata);die;
        $permitted = $this->UPLOAD_PERMITTED_FILES[$permitted];        
        // loop through and deal with the files
        foreach($formdata as $file) {
			if (!is_array($file)) continue;
            // replace spaces with underscores
            $filename = str_replace(' ', '_', $file['name']);
            // assume filetype is false
            $typeOK = false;
            // check filetype is ok

            foreach($permitted as $type) {
                    if($type == $file['type']) {
                            $typeOK = true;
                            break;
                    }
            }

            // if file type ok upload the file
            if($typeOK) {
                    // switch based on error code
                switch($file['error']) {
                    case 0:
                        // check filename already exists
                        if(!file_exists($folder_url.'/'.$filename)) {
                            // create full filename
                            $full_url = $folder_url.'/'.$filename;
                            $url = $rel_url.'/'.$filename;
                            // upload the file
                            $success = move_uploaded_file($file['tmp_name'], $url);
                        } else {
                            // create unique filename and upload file
                            ini_set('date.timezone', 'Europe/London');
                            $now = date('Y-m-d-His');
                            $full_url = $folder_url.'/'.$now.$filename;
                            $url = $rel_url.'/'.$now.$filename;
                            $success = move_uploaded_file($file['tmp_name'], $url);
                        }
                        // if upload was successful
                        if($success) {
                            // save the url of the file
                            $result['urls'][] = $url;
                        } else {
                            $result['errors'][] = "Error uploaded $filename. Please try again.";
                        }
                        break;
                    case 3:
                        // an error occured
                        $result['errors'][] = "Error uploading $filename. Please try again.";
                            break;
                    default:
                        // an error occured
                        $result['errors'][] = "System error uploading $filename. Contact webmaster.";
                        break;
                }
            } elseif($file['error'] == 4) {
                // no file was selected for upload
                $result['nofiles'][] = "No file Selected";
            } else {
                // unacceptable file type
                $result['errors'][] = "$filename cannot be uploaded. Acceptable file types: gif, jpg, png.";
            }
        }
        return $result;
    }

    /**
     * Descarga un archivo de una url y lo coloca en un directorio
     * @param string $url Url del archivo a descargar
     * @param string $dir Directorio local donde se colocara el archivo
     * @return mixed Nombre del archivo solicitado o false si hay algun error
     */
    function getfile($url, $dir){
        $filename = substr($url,strrpos($url,'/'),strlen($url));
        $result = file_put_contents($dir.$filename, file_get_contents($url));
        return $result ? str_replace('/','',$filename) : false;
    }
    /**
     * Descomprime un archivo zip
     * @param string $filename Nombre del archivo zip a descomprimir
     * @param string $destination Directorio donde se extraera el contenido del zip
     * @return string Nombre de los archivos descomprimidos
     */
    function unzip_file($filename, $destination){
        $zip = zip_open($filename);
        $filename = '';
        if (is_resource($zip)) {
            while ($zip_entry = zip_read($zip)) {
                $filename = $destination.zip_entry_name($zip_entry);
                if (file_exists($filename)) unlink($filename);
                $fp = fopen($filename, "w");
                if (zip_entry_open($zip, $zip_entry, "r")) {
                    $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
                    fwrite($fp,"$buf");
                    zip_entry_close($zip_entry);
                    fclose($fp);
                }
            }
            zip_close($zip);
            return $filename;
        } else return false;
    }
    
    /**
     * Comprime un archivo zip
     * @param string $filename Nombre del archivo zip a descomprimir
     * @param string $destination Directorio donde se extraera el contenido del zip
     * @return string Nombre de los archivos descomprimidos
     */
    function zip_file($filename, $files){
        $zip = new ZipArchive();
        if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) {
            return false;
        }
        foreach($files as $file){
            $f = explode(DS,$file);
            $f = $f[count($f)-1];
            $zip->addFile($file,$f);
        }
        $zip->close();
    }

    /**
     * Desliga a un modelo de sus relaciones
     * @param mixed $object Modelo a desligar de relaciones
     * @param array $except Excepciones
     */
    public function unbindModelAll(&$object = null, $except = array()) {		
            if(!is_array($object)){
                    $objects = array($object);
            } else {
                    $objects = $object;
            }

            if(!is_array($except)){
                    $except = array();
            }
            foreach($objects as $object ){
                    foreach ($object->belongsTo as $model=>$info){
                       if(array_search($model, $except) == false)
                                    $unbind['belongsTo'][] = $model;
                    }
                    foreach ($object->hasOne as $model=>$info){
                            if(array_search($model, $except) == false)
                                    $unbind['hasOne'][] = $model;
                    }
                    foreach ($object->hasMany as $model=>$info){
                             if(array_search($model, $except) == false)
                                    $unbind['hasMany'][] = $model;
                    }
                    foreach ($object->hasAndBelongsToMany as $model=>$info){
                             if(array_search($model, $except) == false)
                                    $unbind['hasAndBelongsToMany'][] = $model;
                    }
                    $object->unbindModel($unbind);
            }
    }

    function escrituraCentroDist($id = null){
        $aro = $this->Aro->find('first', array( // obtengo el aro para el usuario activo
            'conditions'=>array('model'=>'Usuario','foreign_key'=>$this->_usuario['id']),
            'recursive'=>-1
        ));

        $centroDist = $this->ArosCentroDist->find('first', array( // consulto si tiene privilegio sobre el cd
            'conditions'=>array(
                'aro_id'=>$aro['Aro']['id'],
                'centro_dist_id'=>$id
            ),
            'fields'=>array('escritura')
        ));

        if (isset($centroDist['ArosCentroDist']['escritura'])){
            return $centroDist['ArosCentroDist']['escritura'];
        } else {
            $aro = $this->Aro->find('first', array( // obtengo el aro del grupo al que pertenece el usuario activo
                'conditions'=>array('model'=>'Grupo','foreign_key'=>$this->_usuario['grupo_id']),
                'recursive'=>-1
            ));
            $centroDist = $this->ArosCentroDist->find('first', array( // consulto si tiene privilegio sobre el cd
                'conditions'=>array(
                    'aro_id'=>$aro['Aro']['id'],
                    'centro_dist_id'=>$id
                ),
                'fields'=>array('escritura')
            ));

            if (isset($empresas['ArosCentroDist']['escritura']))
                return $empresas['ArosCentroDist']['escritura'];
            else
                return false;

        }
    }

    function beforeRender(){
		if(isset($this->params['url']['debug'])){
			Configure::write('debug', 2);
		}
            //restableciendo información de session al hacer peticiones AJAX
            $ejercicio	= $this->Session->read('Ejercicio');
            $usuario 	= $this->Session->read('Usuario');

            if ( $this->RequestHandler->isAjax() ) {
                    $this->Session->write('Usuario', null ); //reseteando la sesion de usuario
                    $this->Session->write('Usuario', $usuario ); // re-asignando la sesion de usuario
                    $this->Session->write('Ejercicio', null ); //reseteando la sesion de ejercicio
                    $this->Session->write('Ejercicio', $ejercicio ); //re-asignando la sesion de ejercicio
            }
            $this->setBusqueda();            
    }

    public function beforeFilter(){
        // validar si se requiere usuario activo para navegar y el acl
        $this->__validarLoginStatus();		
        if ($this->RequestHandler->isAjax()) {
            $this->layout = 'ajax';
        } else {
            if (!in_array('Javascript',$this->helpers))
                    $this->helpers += 'Javascript';
            if (!in_array('Ajax',$this->helpers))
                    $this->helpers += 'Ajax';

            // validando aperturas temporales
            $acoRight = $this->Acl->Aco->find('first',array(
                'conditions'=>array('alias'=>$this->name),
                'recursive'=>-1
            ));
            if ($acoRight['Aco']['con_cierre']){
                switch ($this->getTipoAccion()){
                    case 'read':
                        break;
                    default: // create, update, delete
                        $this->_ejercicio   = $this->Session->read('Ejercicio');
                        list($dia,$mes,$anyo) = explode('/',$this->fechaTrabajo());
                        if (!$this->Cierre->esExcepcion(
                                $this->_usuario['Tercero']['empresa_id'],
                                $this->_usuario['Tercero']['centro_dist_id'],
                                $this->getModulo(),
                                $this->_usuario,
                                $anyo,
                                $mes,
                                $dia)){
                            $this->Session->setFlash('El dia seleccionado esta cerrado.');
                            $this->redirect(array('action'=>'index'));
                        }
                        break;
                }
            }
        }
    }

    public function afterFilter(){
        if ($this->externalAccess){
            $this->Session->destroy('Usuario');
            $this->Session->destroy('Ejercicio');
            $this->externalAccess = false;
        }        
    }

    /**
     * Valida automaticamente al cargar todas las paginas: permisos, cierres, aperturas, etc.
     */
    function  __validarLoginStatus(){
        $flag = false;
        $keys = array_keys($this->loginExceptions);
        for($i = 0; $i < count($keys) && !$flag; $i++){
            $flag = $keys[$i] == $this->name;
            $k = $keys[$i];
        }
        if ($flag){
            if (is_array($this->loginExceptions[$k])){
                $flag = false;
                for($i = 0; $i < count($this->loginExceptions[$k]) && !$flag; $i++){
                    $flag = $this->loginExceptions[$k][$i] == $this->action;
                }
            }
            else if ($this->action == $this->loginExceptions[$k]){
                $flag = true;
            }
            else if (trim($this->loginExceptions[$k]) == ''){
                $flag = true;
            }
        }
        if(!$flag){
            $verified = false;
            // verificando si el user y pass vienen en la querystring (reportes)
            if (isset($this->params['url']['user']) &&
                    isset($this->params['url']['password'])){
                $user = $this->params['url']['user'];
                $password = $this->params['url']['password'];
                $exercice = $this->params['url']['exercice'];
                $period = $this->params['url']['period'];                
                $day = $this->params['url']['day'];
                $centro_dist = $this->params['url']['centro_dist_id'];                
                $usuario = $this->Usuario->validarLogin(array('usuario'=>$user,'password'=>$password),false);
                $this->externalAcess = $verified;

                if($usuario != false){                	
                    if (!isset($exercice) || empty($exercice)){
                        $now = Date('d/m/Y');
                        $parts = split('/',$now);
                        $this->Ejercicio->recursive = -1;
                        $ejercicio = $this->Ejercicio->find('first', array(
                            'fields'=>array('id','codigo','fecha_inicial','fecha_final'),
                            'conditions'=>array('activo'=>true,'cerrado'=>false, 'codigo'=>$parts[2]),
                            'order'=>array('id'=>'desc')
                        ));
                    } else {
                        $now = Date('d/m/Y');
                        $parts = split('/',$now);
                        $this->Ejercicio->recursive = -1;
                        $ejercicio = $this->Ejercicio->find('first', array(
                            'fields'=>array('id','codigo','fecha_inicial','fecha_final'),
                            'conditions'=>array('id'=>$exercice),
                            'order'=>array('id'=>'desc')
                        ));
                        $parts[2] = $ejercicio['Ejercicio']['codigo'];                        
                    }
                    $parts[1] = !isset($period) || empty($period)?$parts[1]:$period;
                    $parts[0] = !isset($day) || empty($day)?$parts[1]:$day;
                    
                    if (!isset($ejercicio['Ejercicio']['id']) || empty($ejercicio['Ejercicio']['id'])){
                        $this->Ejercicio->recursive = -1;
                        $ejercicio = $this->Ejercicio->find('first', array(
                            'fields'=>array('id','codigo','fecha_inicial','fecha_final'),
                            'conditions'=>array('activo'=>true,'cerrado'=>false),
                            'order'=>array('id'=>'desc')
                        ));
                        if (!isset($ejercicio['Ejercicio']['id']) || empty($ejercicio['Ejercicio']['id'])){
                            $this->Session->setFlash('No existe Ejercicio aperturado');
                            $this->Session->destroy('Usuario');
                            $this->Session->destroy('Ejercicio');
                            $this->redirect(array('controller'=>'Usuarios','action'=>'login'));
                        }
                    }
                	if (isset($centro_dist) && !empty($centro_dist)){
                            $usuario['Tercero']['centro_dist_id'] = $centro_dist;
                            $this->CentroDist->recursive = -1;
                            $data = $this->CentroDist->find('first',array(
                                'conditions'=>array('CentroDist.id'=>$centro_dist)
                            ));
                            $usuario['CentroDist'] = $data['CentroDist'];
                            $usuario['CentroDist']['escritura'] = $this->escrituraCentroDist($centro_dist);
                	}
                    $ejercicio['Ejercicio']['Actual']['periodo_id'] = empty($period)?(int)$parts[1]:(int)$period;
                    $ejercicio['Ejercicio']['Actual']['fecha'] = $now;
                    $ejercicio['Ejercicio']['Actual']['dia'] = (int)$parts[0];
                    $ejercicio['Ejercicio']['Actual']['mes'] = $this->months[$ejercicio['Ejercicio']['Actual']['periodo_id']-1];
                    $ejercicio['Ejercicio']['Actual']['anyo'] = (int)$parts[2];

                    $usuario['grupos_despacho'] = $this->grupos_despacho = array_keys($this->Grupo->find('list',array(
                        'conditions'=>array(
                            'activo'=>true,
                            'despacho'=>true
                        ),
                        'recursive'=>-1
                    )));
                    $usuario['logistica'] = $this->logistica =  array_keys($this->Grupo->find('list',array(
                        'conditions'=>array(
                            'activo'=>true,
                            'logistica'=>true
                        ),
                        'recursive'=>-1
                    )));
                    $usuario['gerencia'] = $this->gerencia  = array_keys($this->Grupo->find('list',array(
                        'conditions'=>array(
                            'activo'=>true,
                            'gerencia'=>true
                        ),
                        'recursive'=>-1
                    )));
					
                    $this->Session->write('Usuario', $usuario);
                    $this->Session->write('Ejercicio', $ejercicio['Ejercicio']);
                } else{
                    $this->Session->setFlash('Nombre de usuario o contraseña incorrecta');
                }
            }
//            return true;
            if(!$this->Session->check('Usuario') && !$verified){
                $this->Session->setFlash('La URL que intenta acceder requiere iniciar sesión.');
                $this->redirect('/Usuarios/login?pag='.$this->params['url']['url']);                
            } else {
                // controlando la acl
                $this->_ejercicio   = $this->Session->read('Ejercicio');
                $this->_usuario     = $this->Session->read('Usuario');
                $this->grupos_despacho    = $this->_usuario['grupos_despacho'];
                $this->logistica          = $this->_usuario['logistica'];
                $this->gerencia           = $this->_usuario['gerencia'];

                $aro = array('model'=>'Usuario', 'foreign_key'=>$this->_usuario['id']);

                $aco = "{$this->name}/{$this->action}";
                try{
                    $access = $this->Acl->check($aro, $aco); // verificamos el privilegio

                    if ($access){ // verifico el acceso a la empresa o centro de dist
                        $empresa = $this->_usuario['Empresa']['escritura'];
                        $centroDist = $this->_usuario['CentroDist']['escritura'];
                        
                        if (!$empresa || !$centroDist) {
                            $acoRight = $this->Acl->Aco->find('first',array(
                                'conditions'=>array('alias'=>$this->name),
                                'recursive'=>-1
                            ));
                        }
                        if (!$empresa && $acoRight['Aco']['con_cierre']){
                            foreach($this->accessActions as $key=>$value){
                                if ($key == 'read') continue;
                                foreach($value as $s){
                                    if (preg_match($s, $this->action)){
                                        $access = false;
                                        break;
                                    }
                                }
                                if (!$access) break;
                            }
                        }
                        if ($access && !$centroDist && $acoRight['Aco']['con_cierre']){
                            foreach($this->accessActions as $key=>$value){
                                if ($key == 'read') continue;
                                foreach($value as $s){
                                    if (preg_match($s, $this->action)){
                                        $access = false;
                                        break;
                                    }
                                }
                                if (!$access) break;
                            }
                        }
                    }
                } catch(Exception $e){
                    $access = false;
                }
                if (!$access) {
                    $this->Session->setFlash('No se cuenta con privilegios para acceder a esta pagina');
                    $this->redirect('/pages/acceso_denegado?page='.$aco);
                } 
            }
        } 
    }
    /**
     * Une varios modelos (GuiaRemisione, DocumentoVenta) y los renombra a Documento
     * @param array $models Arreglos de datos
     * @return array Arreglo resultante de la union con modelo Documento
     */
    function union($models = array()){
        $res = array();
        $i = 0;
        foreach ($models as $model){
            foreach($model as $document){
                if (array_key_exists('GuiaRemisione', $document)){
                        $this->array_key_rename($document, 'GuiaRemisione', 'Documento');
                        $document['Documento']['codigo_documento_id'] = 109;
                }
                else if (array_key_exists('DocumentoVenta', $document))
                        $this->array_key_rename($document, 'DocumentoVenta', 'Documento');
                $res[$i] = $document;
                $i++;
            }
        }
        return $res;
    }
    /**
     * Ordena un arreglo segun criterios
     * @param array $array Arreglo a ordenar
     * @param array $order Arreglo con los criterios de ordenamiento (Modelo.Campo asc o desc)
     * @return array
     */
    function array_sort($array, $order = null){
        if (!$order)
            return $array;
        for ($i=0; $i < count($array) -1; $i++){
            for ($j=$i +1; $j < count($array); $j++){
                if($this->array_compare($array[$i], $array[$j], $order) < 0){
                    $tmp = $array[$i];
                    $array[$i] = $array[$j];
                    $array[$j] = $tmp;
                }
            }
        }
        return $array;
    }
    /**
     * Inserta un elemento en una posicion especifica de un array
     * @param <type> $array
     * @param <type> $insert
     * @param <type> $position
     * @return <type>
     */
    function array_insert(&$array, $insert, $position = -1) {
        $position = ($position == -1) ? (count($array)) : $position ;
        if($position != (count($array))) {
          $ta = $array;
          for($i = $position; $i < (count($array)); $i++) {
               if(!isset($array[$i])) {
                    die(print_r($array, 1)."\r\nInvalid array: All keys must be numerical and in sequence.");
               }
               $ta[$i+1] = $array[$i];
//               unset($ta[$i]);
          }
          $ta[$position] = $insert;
          $array = $ta;
          //print_r($array);
        } else {
          $array[$position] = $insert;
        }

        ksort($array);
        return true;
    }
    /**
     *
     * @param array $array Arreglo donde se encuentran el elemento a renombrar
     * @param string $key Nombre de la llave a renombrar
     * @param string $newKey Nuevo nombre para la llave
     */
    function array_key_rename(&$array, $key, $newKey){
        $item = $array[$key];
        unset($array[$key]);
        $array[$newKey] = $item;
    }

    /**
     * Compara dos arreglos
     * @param array $array1
     * @param array $array2
     * @param array $order arreglo con los criterios de comparacion (Modelo.campo asc o desc)
     * @return int devuelve 1, -1 o 0
     */
    function array_compare($array1, $array2, $order){
        if (!is_array($order)){
            $order = array($order);
        }
        $res = 0;
        foreach($order as $o){
            $o = explode(' ',$o);
            if (count($o)>1)
                $criteria = up($o[1]);
            else
                $criteria = 'asc';
            $o = $o[0];
            $parts = explode('.',$o);
            $a1 = $array1;
            $a2 = $array2;
            foreach ($parts as $p){
                $a1 = $a1[$p];
                $a2 = $a2[$p];
            }
            if ($a1 > $a2){
                if (low($criteria) == 'asc')
                    $res = -1;
                else
                    $res = 1;
            }
            else if ($a1 < $a2) {
                if (low($criteria) == 'asc')
                    $res = 1;
                else
                    $res = -1;
            }
            else {
                $res = 0;
            }
            if ($res == -1 || $res == 1) break;
        }
        return $res;
    }

    /**
     * Asocia un prefijo a los elementos de un arreglo
     * @param array $source Arreglo fuente
     * @param String $prefix Prefijo a incluir
     * @return array retorna el arreglo con el prefijo incluido
     */
    function setPrefix($source, $prefix){
        $result = array();
        if (is_array($source)){
            foreach($source as $key => $value){
                if (!is_numeric($key) ){
                    if (!is_array($value)) {
                        $result[$prefix.$key] = $value;
                    } else {
                        foreach ($value as $k => $v){
                            if (!is_numeric($k)){
                                if (isset($result[$key]))
                                    $result[$key] += array($prefix.$k=>$v);
                                else
                                    $result[$key] = array($prefix.$k=>$v);
                            } else {
                                if (isset($result[$key]))
                                    $result[$key] += array($k=>$v);
                                else
                                    $result[$key] = array($k=>$v);
                            }
                        }
                    }
                } else {
                    $result[$key] = $value;
                }
            }
        } else $source = $prefix.$source;
        return $result;
    }

    /**
     * Formatea el texto $q para usarlo en una condicion LIKE o ILIKE de consulta '%$q%'
     * @param string $q
     * @return string
     */
    function likeAtCenter($q){
        return "%$q%";
    }

    /**
     * Formatea el texto $q para usarlo en una condicion LIKE o ILIKE de consulta '$q%'
     * @param string $q
     * @return string
     */
    function likeAtBegin($q){
        return "$q%";
    }

    /**
     * Formatea el texto $q para usarlo en una condicion LIKE o ILIKE de consulta '%$q'
     * @param string $q
     * @return string
     */
    function likeAtEnd($q){
        return "%$q";
    }

    /**
     * Envia contenido por ajax al cliente
     * @param array/string $data a enviar al cliente
     * @return JSONP
     */
    function _ajaxify($data=array()){            
		Configure::write('debug', 0);
		//limpiando cualquier echo o print previo
		ob_start();
		$html = ob_get_contents();
		ob_end_clean();
		$this->autoRender = false;
		$this->autoLayout = false;
		if(empty($data)){
			$data = '';//array('Error'=>'no se extablecieron los datos correctamente');
		}
		$this->header('Content-Type: application/json');
		
		echo json_encode($data);
		die;
    }	
	
    /**
     * Para obtener el identificador del modulo al que pertenece el controlador ($this->appModule)
     * @return int retorn el identificador
     */
    function getModulo(){
        switch (up($this->appModule)){            
            case 'ALMACEN':
                return 3;
            case 'LOGISTICA':
                return 4;            
            case 'TESORERIA':
                return 8;            
            case 'ADMINISTRACION':
                return 10;
            default:
                return 0;
        }
    }

    /**
     * Para obtener a que grupo pertenece la eccion (create, read, update, delete)
     * @return string retorna el tipo de accion
     */
    function getTipoAccion(){
        foreach($this->accessActions as $key=>$value){
            foreach($value as $format){
                if (preg_match($format, $this->name.'.'.$this->action)>0)
                        return $key;
            }
        }
        return 'read';
    }

    /**
     * Segun el codigo del centro de distribucion retorna su simbolo
     * @param int $centroDist codigo de deposito
     * @return string simbolo del deposito
     */
    function getCiudad($centroDist){
        switch($centroDist){
            case 50: return 'P';
            case 51: return 'T';
            case 52: return 'I';
            case 53: return 'M';
            case 54: return 'A';
            case 55: return 'C';
            case 56: return 'L';
            case 57: return 'Q';
            case 58: return 'V';
            case 59: return 'N';
            case 60: return 'Y';
            case 61: return 'K';
            default: return 51;
        }
    }

    /**
     * Segun el simbolo del centro de distribucion retorna su codigo
     * @param string $ciudad simbolo del deposito
     * @return int codigo de deposito
     */
    function getCentroDist($ciudad){
        switch($ciudad){
            case 'P': return 50;
            case 'T': return 51;
            case 'I': return 52;
            case 'M': return 53;
            case 'A': return 54;
            case 'C': return 55;
            case 'L': return 56;
            case 'Q': return 57;
            case 'V': return 58;
            case 'N': return 59;
            case 'Y': return 60;
            case 'K': return 61;
            default: return 51;
        }
    }

    /**
     * Segun el codigo del cetro de distribucion retorna su identificador
     * @param int $centroDist codigo del deposito
     * @return int identificador del deposito
     */
    function getCentroDistId($centroDist){
        switch($centroDist){
            case 50: return 1;
            case 51: return 2;
            case 52: return 3;
            case 53: return 4;
            case 54: return 5;
            case 55: return 6;
            case 56: return 7;
            case 57: return 8;
            case 58: return 9;
            case 59: return 10;
            case 60: return 11;
            case 61: return 12;
            default: return 2;
        }
    }
	
    /**
     * Recortar una cadena de texto a n caracteres sin cortar palabras
     * USO:
     *  $string = 'esta oración es demasiado larga';
     *  echo neat_trim($string, 16);
     * 	//Output: 'esta oración es...'
     * @param string $str cadena de texto
     * @param integer $n numero de caracteres a recortar
     * @param mixed $delim indicador de texto largo. Default: '...'
     * @return string texto procesado
     **/
    function neat_trim($str, $n, $delim='...') {
       $len = strlen($str);
       if ($len > $n) {
               preg_match('/(.{' . $n . '}.*?)\b/', $str, $matches);
               return rtrim($matches[1]) . $delim;
       }
       else {
               return $str;
       }
    }

    /**
     * Devuelve la ultima actualizacion de la $table wap
     * @param string $table nombre de la tabla (clientes, productos, vendedores)
     * @return date fecha de ultima actualizacion
     */
    function getLastUpdate($table = ''){
            $centro = $this->CentroDist->find('first', array(
                    'fields'=>array('fecha_actualizacion_wap'.$table),
                    'conditions'=>array('id'=>$this->centroDistId()),
            ));
            return $centro['CentroDist']['fecha_actualizacion_wap'.$table];
    }
    
    /**
     * Actualiza la fecha de actualizacion de $table
     * @param string $table nombre de la tabla actualizada (clientes, productos, vendedores)
     * @param string $datetime 
     * @return boolean
     */
    function updateLastUpdate($table = '', $datetime = 'now()'){
            return $this->CentroDist->save(array(
                    'id'=>$this->centroDistId(),
                    'fecha_actualizacion_wap'.$table=>$datetime
            ));
    }

    function empresaId(){
            return $this->_usuario['Tercero']['empresa_id'];
    }

    function centroDistId(){
            return $this->_usuario['Tercero']['centro_dist_id'];
    }

    function ejercicioId($date = null){
        if (empty($date)){
            if (isset($this->_ejercicio['id']))
                return $this->_ejercicio['id'];
            else {
                $ejercicio = $this->Ejercicio->find('first',array(
                    'conditions'=>array(
                        'codigo'=>date('Y'),
                        'activo'=>true
                    ),
                    'recursive'=>-1
                ));
                return $ejercicio['Ejercicio']['id'];
            }
        } else {
        	if(is_array($date)){
        		$date[2] = $date['year'];	
        	} else {
	            if (strpos($date,'-') != false)
	                $date = explode('-',$date);
	            else
	                $date = explode('/',$date);
        	}

            $ejercicio = $this->Ejercicio->find('first',array(
                'conditions'=>array(
                    'codigo'=>$date[2],
                    'activo'=>true
                ),
                'recursive'=>-1
            ));
            return $ejercicio['Ejercicio']['id'];
        }
    }

    function periodoId($date = null){
        if (empty($date)){
            if (isset($this->_ejercicio['Actual']['periodo_id']))
                return $this->_ejercicio['Actual']['periodo_id'];
            else
                return date('m');
        } else {
        	if(is_array($date)){
        		$date[1] = $date['month'];	
        	} else {	
	            if (strpos($date,'-') != false)
	                $date = explode('-',$date);
	            else
	                $date = explode('/',$date);
        	}
            return $date[1];
        }
    }

    function usuarioId(){
            return $this->_usuario['id'];
    }

    function fechaTrabajo(){
        return $this->_ejercicio['Actual']['fecha'];
    }

    function carpetaId(){
        return isset($this->_ejercicio['Actual']['carpeta_id'])?$this->_ejercicio['Actual']['carpeta_id']:1;
    }

    function getBusqueda($busqueda = ''){
            $q = $busqueda;
            $text = $busqueda;
            if(!empty($busqueda)){
                $q = str_replace(';','|', $busqueda);
                $text = $busqueda;
            //verificando si se hizo busqueda por parametro url
            } else if(!empty($this->params['url']['q'])){
                $q = str_replace(';','|', $this->params['url']['q']);
                $text = $this->params['url']['q'];
            } else if(!empty($this->params['form']['q'])){
                $q = str_replace(';','|', $this->params['form']['q']);
                $text = $this->params['form']['q'];
            } else if(!empty($q)){
                $q = str_replace(';','|',$q);
                $text = $q;
            }
		
            if($q != ''){
                    $upper = '|'.strtoupper($q);
                    $lower = '|'.strtolower($q);
                    $q = '('.$q.$upper.$lower.')';
            }
            AppController::$text_buscar = $text;
            AppController::$limit_index = $this->limite;
		$this->set('q',$text);
            return $q;
    }
	
    function setBusqueda($busqueda = ''){
     	if(!empty($busqueda)){           
            $text = $busqueda;
            //verificando si se hizo busqueda por parametro url
         } else if(!empty($this->params['url']['q'])){            
            $text = $this->params['url']['q'];
         } else if(!empty($this->params['form']['q'])){            
            $text = $this->params['form']['q'];
         } else {
         	$text = '';
         }
         AppController::$text_buscar = $text;
         AppController::$limit_index = $this->limite;
         return $text;         
    }
    //******* PDF Vendedor extension
    
    function CreatePdf($arg = null){
            App::import('Vendor', 'mpdf', array('file' =>'mpdf44'.DS.'mpdf.php'));
            Configure::write('debug', 0);

            $_arg = array();
            $_arg['codepage'] = 'win-1252';
            $_arg['format'] = 'A4';
            $_arg['default_font_size'] = '';
            $_arg['default_font'] = '';
            $_arg['margin_left'] = 20;
            $_arg['margin_right'] = 5;
            $_arg['margin_top'] = 15;
            $_arg['margin_bottom'] = 15;
            $_arg['margin_header'] = 5;
            $_arg['margin_footer'] = 10;
            $_arg['orientation'] = '';
            $_arg['style'] = 'printer.css';
            $_arg['time_limit'] = 30;

            if(empty($arg)){$arg = array();}
            $_arg = array_merge($_arg, $arg);

            self::$_mpdf = new mPDF(
                    $_arg['codepage'],
                    $_arg['format'],
                    $_arg['default_font_size'],
                    $_arg['default_font'],
                    $_arg['margin_left'],
                    $_arg['margin_right'],
                    $_arg['margin_top'],
                    $_arg['margin_bottom'],
                    $_arg['margin_header'],
                    $_arg['margin_footer'],
                    $_arg['orientation']);

            if($_arg['time_limit'] != 30){
                    set_time_limit((int)$_arg['time_limit']);
            }

            $stylesheet = file_get_contents($this->path_webroot.'css\\'.$_arg['style']);
            self::$_mpdf->WriteHTML($stylesheet,1);

            self::$_mpdf->defaultheaderfontsize = 10;	/* in pts */
            self::$_mpdf->defaultheaderfontstyle = B;	/* blank, B, I, or BI */
            self::$_mpdf->defaultheaderline = 1; 	/* 1 to include line below header/above footer */
            self::$_mpdf->defaultfooterfontsize = 9;	/* in pts */
            self::$_mpdf->defaultfooterfontstyle = B;	/* blank, B, I, or BI */
            self::$_mpdf->defaultfooterline = 1; 	/* 1 to include line below header/above footer */

            if(empty($arg['header_default']) || ($arg['header_default'] == true)){
                    $this->PrintHeaderDefault();
            }

            if(empty($arg['footer_default']) || ($arg['footer_default'] == true)){
                    $this->PrintFooterDefault();
            }
            return self::$_mpdf;
    }

    public function PrintHeaderDefault(){
            define('_HEADER_DEFAULT_',true);
            /*
            $htmlheader = '<table width="100%" cellpadding="0" cellspacing="0" style="border-bottom:solid 1px #000"><tr valign="middle"><td><img src="'. $this->path_webroot .'img\\logo.jpg" width="40" style="filter: alpha(opacity=50); opacity: .5" /><b>Corporación ADC</b></td></tr></table>';
            self::$_mpdf->SetHTMLHeader($htmlheader);*/
    }

    public function PrintFooterDefault(){
            define('_FOOTER_DEFAULT_',true);
            /*self::$_mpdf->SetFooter('{DATE j-m-Y H:m} '.$this->_usuario['Tercero']['razon_social'].'| |{PAGENO}/{nb}');*/
    }

    public function addStylePDF($style){
            $stylesheet = file_get_contents(str_replace('\\','/',WWW_ROOT.'css\\'.$style));
            self::$_mpdf->WriteHTML($stylesheet,1);
    }
	
    /*parseStringDate
    convertir una fecha de tipo String a tipo Array soportado por cakephp
    params:
            (String) $date : fecha a convertir con formato dd-mm-yyyy  '-' es el separador
            (String) $separator : separador de fecha
    out:
            (Array)
    */
    public function parseStringDate($date, $separator = '/'){
            if(empty($date)){
                    return null;
            }
            if($date == ('00'.$separator.'00'.$separator.'0000')){
                    return null;
            }
            $fecha = explode($separator, $date);
            if(count($fecha)==3){
                    return array(
                            'day'=>$fecha[0],
                            'month'=>$fecha[1],
                            'year'=>$fecha[2]
                    );
            } else {
                    return null;
            }

    }

    function array_regex_find($key, $array){
        foreach ($array as $k=>$item){
            if (preg_match($key, $k)){
                return $k;
            }
        }
        return 0;
    }

    function is_date($fecha){
        //Comprueba si la cadena introducida es de la forma d/m/Y (15/04/1920)
        if (ereg("([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})", $fecha, $bloques)){
            return checkdate($bloques[2], $bloques[1], $bloques[3]);
        } else if (ereg("([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})", $fecha, $bloques)){
            return checkdate($bloques[2], $bloques[3], $bloques[1]);
        } else if (ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $fecha, $bloques)){ // yyyy/mm/dd
            return checkdate($bloques[2], $bloques[3], $bloques[1]);
        } else if (ereg("([0-9]{1,2})-([0-9]{1,2})-([0-9]{4})", $fecha, $bloques)){ // dd-mm-yyyy
            return checkdate($bloques[2], $bloques[1], $bloques[3]);
        } else if (ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $fecha, $bloques)){ // yyyy-mm-dd
            return checkdate($bloques[2], $bloques[3], $bloques[1]);
        } else return false;
        return true;
    }

    //// Nextel Webservice

    function cargarInformacion($xmlInfo, $archivo, $piIdCuenta = 99, $user = 'adc', $password = 'adc'){
        App::import('Vendor', 'nusoap', array('file' =>'nusoap'.DS.'nusoap.php'));

        $cliente = new nusoap_client($this->URL_WSDL, true);
        $resultado  = array();
        if ($cliente->getError()) {
            $this->Session->setFlash('Se ha producido un Error al establecer la conexion al WebService');
            return false;
        } else {
            $headers = '<LoginInfo xmlns="http://tempuri.org/"><User>'.$user.'</User><Password>'.$password.'</Password><Cuenta>'.$piIdCuenta.'</Cuenta></LoginInfo>';
            $resultado = $cliente->call('cargarInformacion', array(
                'xmlInfo'=>$xmlInfo,
                'archivo'=>$archivo,
                'piIdCuenta'=>$piIdCuenta
            ),'','',$headers);


//            echo '<h2>Request</h2>';
//            echo '<pre>' . htmlspecialchars($cliente->request, ENT_QUOTES) . '</pre>';
//            echo '<h2>Response</h2>';
//            echo '<pre>' . htmlspecialchars($cliente->response, ENT_QUOTES) . '</pre>';
//            die;
            // Comprobamos los errores y mostramos el resultado
            if ($cliente->fault) {
                $this->Session->setFlash('Error: La peticion contiene un contenido SOAP invalido');
                return false;
            } else {
                $err = $cliente->getError();
                if ($err) {
                    $this->Session->setFlash('Error: '.$err);
                    return false;
                }
            }
        }
        return $resultado;
    }

    function descargarInformacion($tipoDescarga, $fecha_inicial, $fecha_final, $piIdCuenta = 99, $estado = '*', $user = 'adc', $password = 'adc'){
        App::import('Vendor', 'nusoap', array('file' =>'nusoap'.DS.'nusoap.php'));

        $cliente = new nusoap_client($this->URL_WSDL, true);
        $resultado  = array();
        if ($cliente->getError()) {
            $this->Session->setFlash('Se ha producido un Error al establecer la conexion al WebService');
            return false;
        } else {
            $headers = '<LoginInfo xmlns="http://tempuri.org/"><User>'.$user.'</User><Password>'.$password.'</Password><Cuenta>'.$piIdCuenta.'</Cuenta></LoginInfo>';
            $resultado = $cliente->call('descargar', array(
                'tipoDescarga'=>$tipoDescarga,
                'fecini'=>$fecha_inicial,
                'fecfin'=>$fecha_final,
                'piIdCuenta'=>$piIdCuenta,
                'estado'=>$estado,
            ),'','',$headers);


//            echo '<h2>Request</h2>';
//            echo '<pre>' . htmlspecialchars($cliente->request, ENT_QUOTES) . '</pre>';
//            echo '<h2>Response</h2>';
//            echo '<pre>' . htmlspecialchars($cliente->response, ENT_QUOTES) . '</pre>';
//            die;

            // Comprobamos los errores y mostramos el resultado
            if ($cliente->fault) {
                $this->Session->setFlash('Error: La peticion contiene un contenido SOAP invalido');
                return false;
            } else {
                $err = $cliente->getError();
                if ($err) {
                    $this->Session->setFlash('Error: '.$err);
                    return false;
                }
            }
        }
        return $resultado;
    }

    function limpiarData($tabla, $piIdCuenta = 99, $user = 'adc', $password = 'adc'){
        App::import('Vendor', 'nusoap', array('file' =>'nusoap'.DS.'nusoap.php'));

        $cliente = new nusoap_client($this->URL_WSDL, true);
        $resultado  = array();
        if ($cliente->getError()) {
            $this->Session->setFlash('Se ha producido un Error al establecer la conexion al WebService');
            return false;
        } else {
            $headers = '<LoginInfo xmlns="http://tempuri.org/"><User>'.$user.'</User><Password>'.$password.'</Password><Cuenta>'.$piIdCuenta.'</Cuenta></LoginInfo>';
            $resultado = $cliente->call('limpiarInformacion', array(
                'tabla'=>$tabla,
                'piIdCuenta'=>$piIdCuenta
            ),'','',$headers);

            // Comprobamos los errores y mostramos el resultado
            if ($cliente->fault) {
                $this->Session->setFlash('Error: La peticion contiene un contenido SOAP invalido');
                return false;
            } else {
                $err = $cliente->getError();
                if ($err) {
                    $this->Session->setFlash('Error: '.$err);
                    return false;
                }
            }
        }
        return $resultado;
    }

    function explodeParts($string, $parts = array()){
        $start = 0;
        $length = strlen($string);
        $result = array();
        foreach($parts as $part){
            $length = $part;
            $s = substr($string, $start, $length);
            array_push($result, $s);
            $start += $part;
        }
        $s = substr($string, $start);
        array_push($result, $s);
        return $result;
    }

    function webserviceToDateTime($datetime){
        list($y,$m,$d,$h,$i,$s) = $this->explodeParts($datetime, array(4,2,2,2,2,2));
        return date('d/m/Y h:i:s', mktime($h, $i, $s, $m, $d, $y));
    }
    
    /**
     * 
     * @param array $models
     * @param string $group_format
     * @param string $format
     * @author Iván
     * @tutorial 
     * Metodo que permite rextraer  los mensajes de validacion de los modelo que usa el controlador
     * para pasarlos a la vista     
     */
    
    function validationModels($models=array(), $group_format = '<ul>%texto</ul>', $format= '<li>%texto</li>'){    	
    	if(empty($models)){
    		$controller = new ReflectionObject($this);
    		$models = array();
    		foreach($this->uses as $model){    			    				
    			$propiedad = $controller->getProperty($model);
    			$propiedad->setAccessible(true);
    			$modelo = 	$propiedad->getValue($this);    			
    			$modelos[] = 	$modelo;
    		}    		
    		return $this->validationModels($modelos);    		
    	}
    	
    	$mensaje = '';
    	if(!is_array($models)){    			
    		$models = array($models);
    	} 
    	foreach($models as $model){    		
    		foreach($model->validationErrors as $msg){
    			$mensaje .= str_replace('%texto',$msg,$format);
    		}
    	}
    	return 	str_replace('%texto',$mensaje,$group_format);
    }
}
?>